<script setup lang="tsx">
/* 可编辑表格（内定只支持两列key-value），双向绑定对象，支持Form组件引用 */
import { computed, reactive, ref, watch, withDefaults } from 'vue'
import { ElButton, ElInput, useFormDisabled } from 'element-plus'
import { useDesign } from '@sat/shared-hooks'
import { Table } from '../../Table'
import type { TableColumn } from '../../Table'

interface EditableTableData {
  key: any
  value: any
  _disabled?: boolean
  [x: string]: any
}

const props = withDefaults(
  defineProps<{
    disabled?: boolean
  }>(),
  {
    disabled: false,
  },
)
const emit = defineEmits(['change'])
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('e-table')

const inputDisabled = computed(() => {
  return props.disabled ?? useFormDisabled()
})

const modelValue = defineModel<Recordable>('modelValue', {
  default: {},
})

const columns = reactive<TableColumn[]>([
  {
    field: 'key',
    label: '参数名',
    slots: {
      default: (scope) => {
        return (
          <>
            <ElInput
              disabled={scope.row._disabled}
              v-model={scope.row.key}
            >
            </ElInput>
          </>
        )
      },
    },
  },
  {
    field: 'value',
    label: '参数值',
    slots: {
      default: (scope) => {
        return (
          <>
            <ElInput
              disabled={scope.row._disabled}
              v-model={scope.row.value}
            >
            </ElInput>
          </>
        )
      },
    },
  },
])

const unionColumns = computed(() => {
  if (inputDisabled.value)
    return columns

  return columns.concat([
    {
      field: 'action',
      label: '操作',
      slots: {
        default: (scope) => {
          const rowDisabled = Boolean(scope.row._disabled)
          return (
            <>
              {rowDisabled
                ? (
                  <ElButton
                    v-show={!inputDisabled.value}
                    size="small"
                    onClick={() => handleEdit(scope.$index, scope.row)}
                  >
                    编辑
                  </ElButton>
                  )
                : (
                  <ElButton
                    v-show={!inputDisabled.value}
                    type="primary"
                    size="small"
                    onClick={() => hold(scope.$index, scope.row)}
                  >
                    保存
                  </ElButton>
                  )}
              <ElButton
                v-show={!inputDisabled.value}
                type="danger"
                size="small"
                onClick={() => handleDelete(scope.$index, scope.row)}
              >
                删除
              </ElButton>
            </>
          )
        },
      },
    },
  ])
})

const tableData = ref<EditableTableData[]>([])

watch(
  modelValue,
  (val) => {
    if (!val) {
      val = {}
      modelValue.value = val
    }
    tableData.value = Object.entries(val).map((item) => {
      return {
        key: item[0],
        value: item[1],
        _disabled: true,
      }
    })
  },
  {
    immediate: true,
  },
)

/* 获取数据 */
function getData() {
  const assuredData = tableData.value?.filter?.((item) => {
    let flag = item._disabled
    if (!item.key)
      flag = false

    return flag
  })
  const res: Recordable = {}
  assuredData.forEach((item) => {
    res[item.key] = item.value
  })
  return res
}
/* 添加新的一行，默认是可编辑状态 */
function addLine() {
  const obj: EditableTableData = {
    key: '',
    value: '',
  }
  obj._disabled = false
  tableData.value.push(obj)
}

/* 编辑 */
function handleEdit(index, row) {
  row._disabled = false
}
/* 保存 */
function hold(index, row) {
  row._disabled = true
  modelValue.value = getData()
  emit('change', modelValue.value)
}
/* 删除 */
function handleDelete(index, _row) {
  tableData.value.splice(index, 1)
  modelValue.value = getData()
  emit('change', modelValue.value)
}

function setData(data: any[]) {
  tableData.value = data.map?.((item) => {
    return {
      ...item,
      _disabled: true,
    }
  })
}

defineExpose({
  setData,
  getData,
})
</script>

<template>
  <div class="w-full" :class="[prefixCls]">
    <ElButton
      v-show="!inputDisabled"
      size="small"
      type="primary"
      class="mb-10px"
      @click="addLine"
    >
      添加一行
    </ElButton>
    <Table :columns="unionColumns" :data="tableData" v-bind="$attrs" />
  </div>
</template>

<style lang="less" scoped></style>
